home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / ru2 < prev    next >
Encoding:
Internet Message Format  |  1989-04-19  |  21.4 KB

  1. Subject:  v18i104:  Rwho with a users(1)-style output
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: pkern <pkern@csri.toronto.edu>
  7. Posting-number: Volume 18, Issue 104
  8. Archive-name: ru2
  9.  
  10. Print a users(1)-style list of names for each host in the rwho spool directory
  11.  
  12. Before running make, choose the proper CAPLIB (ie. -ltermlib or -ltermcap).
  13.  
  14. Since rwho is pretty much a BSD animal (I think), the code has only been
  15. tested on a vax (BSD 4.2), on a Sun 4 and on Sun 3s (SunOS 3.5 & 4.0)
  16.  
  17. Possible ru options:
  18.     -a    print all names regardless of idle time (not unlike "rwho -a").
  19.     -c    for repeated names, print the total number of repeats.
  20.     -d    like -s but list hosts alphabetically, regardless of their subdomains.
  21.     -m    don't drop repeated names.
  22.     -r     mimic rwho(1) output.
  23.     -s    print lists by host instead of by subdomain.
  24.     -u     list uptimes like ruptime(1).
  25.     -w     start a fresh line before the output can wrap around.
  26.     -h    restrict output to those hosts given on the command line.
  27.     -l     restrict output to those systems hosting the given users.
  28.     -D    restrict output to those hosts within the given subdomain.
  29.  
  30. #! /bin/sh
  31. # This is a shell archive.  Remove anything before this line, then unpack
  32. # it by saving it into a file and typing "sh file".  To overwrite existing
  33. # If this archive is complete, you will see the following message at the end:
  34. #        "End of shell archive."
  35. # Contents:
  36. #   Readme Makefile ru.l ru.c
  37. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  38. if test -f Readme -a "${1}" != "-c" ; then 
  39.   echo shar: Will not over-write existing file \"Readme\"
  40. else
  41. echo shar: Extracting \"Readme\" \(2176 characters\)
  42. sed "s/^X//" >Readme <<'END_OF_Readme'
  43. XRu:
  44. X print a users(1)-style list of names for each host in the rwho spool directory
  45. XBefore running make, choose the proper CAPLIB (ie. -ltermlib or -ltermcap).
  46. X
  47. XSince rwho is pretty much a BSD animal (I think), the code has only been
  48. Xtested on a vax (BSD 4.2), on a Sun 4 and on Sun 3s (SunOS 3.5 & 4.0)
  49. X
  50. XPossible ru options:
  51. X-a    print all names regardless of idle time (not unlike "rwho -a").
  52. X-c    for repeated names, print the total number of repeats.
  53. X-d    like -s but list hosts alphabetically, regardless of their subdomains.
  54. X-m    don't drop repeated names.
  55. X-r     mimic rwho(1) output.
  56. X-s    print lists by host instead of by subdomain.
  57. X-u     list uptimes like ruptime(1).
  58. X-w     start a fresh line before the output can wrap around.
  59. X-h    restrict output to those hosts given on the command line.
  60. X-l     restrict output to those systems hosting the given users.
  61. X-D    restrict output to those hosts within the given subdomain.
  62. X
  63. XThanks to getopt(3) the options listed above can be mixed and matched at will.
  64. XFor example:
  65. X    ru -ral joe jack
  66. X    prints rwho-style output (-r) of those systems hosting users
  67. X    joe and/or jack (-l joe jack) regardless of their idle-times (-a).
  68. X    ru -smD ai
  69. X    lists host-by-host (-s) the users (including repeated logins (-m))
  70. X    within the ai subdomain (-D ai).
  71. X
  72. XSome options override others (eg. -d overrides -s, -m overrides -c,
  73. X-u overrides -r). All options are subject to restriction by -h or -l and/or -D.
  74. X
  75. XRu only uses existing spooled data so the displayed info could be up to 5 mins    
  76. Xout of date. SUN's rusers(1c) seems to actively poll daemons throughout the
  77. Xlocal network ... which means it provides up-to-date info but it seems to
  78. Xtake an awfully long time and also requires the services of another daemon.
  79. X
  80. XRu was first written when everything here was still mainly on vaxes
  81. X(it was also called rusers, then) so I was pleasantly surprised to discover
  82. XSUN's rusers after CSRI made the final move to Suns. It was kind of interesting
  83. Xto see how they paralleled each other and how they differed (ie. options, etc.).
  84. X
  85. XAnyhow, hope it's useful.
  86. X
  87. XP. Kern
  88. Xpkern@csri.toronto.edu
  89. Xpkern@csri.utoronto.ca
  90. Xpkern@utcsri.uucp (..!utzoo!utcsri!pkern, ..!uunet!utai!pkern)
  91. END_OF_Readme
  92. if test 2176 -ne `wc -c <Readme`; then
  93.     echo shar: \"Readme\" unpacked with wrong size!
  94. fi
  95. # end of overwriting check
  96. fi
  97. if test -f Makefile -a "${1}" != "-c" ; then 
  98.   echo shar: Will not over-write existing file \"Makefile\"
  99. else
  100. echo shar: Extracting \"Makefile\" \(213 characters\)
  101. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  102. X#
  103. X# Makefile for ru
  104. X#
  105. X
  106. X# CFLAGS=    -Ddebug -g
  107. XCFLAGS=    -O -s
  108. X
  109. X# CAPLIB=    -ltermlib
  110. XCAPLIB=    -ltermcap
  111. X
  112. Xru:    ru.c
  113. X    $(CC) $(CFLAGS) -o $@ ru.c $(CAPLIB)
  114. X
  115. Xman:    ru.l
  116. X    nroff -man ru.l > ru.man
  117. X
  118. Xclean:
  119. X    -rm -f *.o a.out core
  120. END_OF_Makefile
  121. if test 213 -ne `wc -c <Makefile`; then
  122.     echo shar: \"Makefile\" unpacked with wrong size!
  123. fi
  124. # end of overwriting check
  125. fi
  126. if test -f ru.l -a "${1}" != "-c" ; then 
  127.   echo shar: Will not over-write existing file \"ru.l\"
  128. else
  129. echo shar: Extracting \"ru.l\" \(2304 characters\)
  130. sed "s/^X//" >ru.l <<'END_OF_ru.l'
  131. X.TH RU L Feb/89 local 
  132. X.UC
  133. X.SH NAME
  134. Xru \- compact lists of users on all "visible" systems
  135. X.SH SYNOPSIS
  136. X.B "ru [-acdmrsuw] [-D domain] [-h host ... | -l user ...]"
  137. X.SH DESCRIPTION
  138. X.I Ru
  139. Xlists the login names of the users currently on all visible systems.
  140. X.SH Options
  141. X.IP -a
  142. Xlist all users, regardless of their login idle time (\fIrwho(1)\fP-inspired).
  143. X.IP -c
  144. Xshow a count for multiply-logged users.
  145. X.\"When combined with -s, include a count of hosts in each domain.
  146. X.IP -d
  147. Xlist hosts alphabetically, regardless of their sub-domains
  148. X.\"group hosts within their sub-domains
  149. X(forces -s option).
  150. X.IP -m
  151. Xshow multiple logins (overrides -c option).
  152. X.\"squeeze (ignore) multiple logins.
  153. X.IP -r
  154. Xproduce \fIrwho(1)\fP-style output (forces -s option).
  155. X.IP -s
  156. Xlist users host-by-host instead of domain-by-domain.
  157. X.\"list users domain-by-domain instead of host-by-host.
  158. X.IP -u
  159. Xdisplay uptimes (see \fIruptime(1)\fP) (forces -s option).
  160. X.IP -w
  161. Xbreak lines before they wrap around the screen.
  162. X.\"allow lines to wrap around (ie. single line per heading).
  163. X.IP "-D domain"
  164. Xlist only users logged on hosts in the given domain.
  165. X.IP "-h host ..."
  166. Xlist only users logged on to the specified host(s).
  167. X.IP "-l user ..."
  168. Xlist only hosts with the given user(s) (forces -s option).
  169. X.PP
  170. XThe -h and -l options are mutually exclusive since they
  171. Xboth use the remaining arguments as a search list.
  172. XEither option should be followed by at least one name.
  173. X.PP
  174. XAny system for which data can be found in the
  175. X.I rwhod(8c)
  176. Xspooling directory is considered to be a "visible system".
  177. X.SH FILES
  178. X/usr/spool/rwho/whod.*
  179. X.SH SEE ALSO
  180. Xusers(1), rwho(1C), rwhod(8C), ruptime(1C)
  181. X.SH HISTORY
  182. XOriginally created by splicing pieces of
  183. X.I rwho(1)
  184. Xsource into
  185. X.I users(1)
  186. Xsource.
  187. XRewritten to try to clean up the hacked code
  188. Xand to make it easier to add (or delete) options.
  189. X.PP
  190. XBug fixes, enhancements and help provided by
  191. X nispa@hutcs.hut.fi <Tapani Lindgren>,
  192. X kusalik@damask.uucp,
  193. X pkh%cs.nott.ac.uk@nss.cs.ucl.ac.uk <Kevin Hopkins>,
  194. X lamy@ai.toronto.edu <Jean-Francois Lamy>,
  195. X moraes@ai.toronto.edu <Mark Moraes>
  196. X.SH BUGS
  197. XWith the -h option,
  198. X.I ru
  199. Xdoesn't care if a host's spool file hasn't
  200. Xbeen updated within the last 5 minutes.
  201. X.sp
  202. XThis might be considered a good example of option overload.
  203. X.SH CONTACT
  204. Xpkern@utcsri.uucp or pkern@csri.toronto.edu
  205. END_OF_ru.l
  206. if test 2304 -ne `wc -c <ru.l`; then
  207.     echo shar: \"ru.l\" unpacked with wrong size!
  208. fi
  209. # end of overwriting check
  210. fi
  211. if test -f ru.c -a "${1}" != "-c" ; then 
  212.   echo shar: Will not over-write existing file \"ru.c\"
  213. else
  214. echo shar: Extracting \"ru.c\" \(13584 characters\)
  215. sed "s/^X//" >ru.c <<'END_OF_ru.c'
  216. X/*
  217. X * ru - remote users(1)
  218. X *    usage: ru [-acdmrsuw] [-D domain] [-h host ... | -l user ...]
  219. X * List users on all "visible" hosts.
  220. X *
  221. X * Copyright (c) 1989 University of Toronto. All rights reserved.
  222. X * Anyone may use or copy this software, except that it may not be
  223. X * sold for profit, that this copyright notice remain intact, and that
  224. X * credit is given where it is due. The University of Toronto and the
  225. X * author make no warranty and accept no liability for this software.
  226. X *
  227. X * Written by P. Kern (pkern@utcsri)
  228. X * with bug fixes and suggestions from
  229. X *    nispa@hutcs.hut.fi <Tapani Lindgren>
  230. X *    kusalik@damask.uucp
  231. X *    pkh%cs.nott.ac.uk@nss.cs.ucl.ac.uk <Kevin Hopkins>
  232. X *    lamy@ai.toronto.edu <Jean-Francois Lamy>
  233. X *    moraes@csri.toronto.edu <Mark Moraes>
  234. X *
  235. X * $Header: ru.c,v 2.9 89/02/26 13:48:36 pkern Exp $
  236. X */
  237. X
  238. X#include <stdio.h>
  239. X#include <sys/types.h>
  240. X#include <sys/stat.h>
  241. X#include <sys/dir.h>
  242. X#include <sys/file.h>
  243. X#include <netdb.h>
  244. X
  245. X#define MINSTR    8        /* minimum string length */
  246. X#define HNSZ    32        /* hostname length */
  247. X#define RWFSZ    HNSZ+5        /* spool-file name length */
  248. X#define MRGN    10        /* margin "tab" size */
  249. X#define HOUR    3600        /* seconds in an hour */
  250. X#define RWPERIOD    300    /* std. 5 minute rwho refresh period */
  251. X#define MAXPORTS    160    /* max tty ports per host */
  252. X
  253. Xstruct rw_utmp {    /* rwho file user info */
  254. X    char tty[MINSTR];    /* user's tty */
  255. X    char name[MINSTR];    /* user's login */
  256. X    long time;        /* login time */
  257. X    long idle;        /* idle time */
  258. X} rut;
  259. X
  260. Xstruct rw_hdr {        /* rwho data/host info */
  261. X    char pad[4];        /* ignore first 4 bytes */
  262. X    int sent, rcvd;        /* time sent,  time rec'vd */
  263. X    char host[HNSZ];    /* host's name */
  264. X    int loadav[3];        /* load averages */
  265. X    int boot;        /* boot date */
  266. X} hdr;
  267. X
  268. Xint rutsize, hdrsize;
  269. X#ifdef debug
  270. X#define RWHODIR    "rwho"
  271. X#else
  272. X#define RWHODIR "/usr/spool/rwho"
  273. X#endif
  274. X
  275. Xlong now;        /* it won't be ... (long now :-) */
  276. Xint n, fd;
  277. Xstruct stat st;
  278. Xchar *hnbuf, *hp;    /* hostname buffer & extra pointer */
  279. Xchar *rubuf, *ep;    /* utmp data buffer & end pointer */
  280. Xchar *program, *domain;
  281. X    /* Flags: if (flag) then ... */
  282. Xint aflag=1;    /* ... only show users with <1 HR idle time */
  283. Xint sflag=1;    /* ... show output by domains (not by hosts) */
  284. Xint mflag=1;    /* ... drop multiple logins */
  285. Xint cflag=0;    /* ... (if mflag) show login counts */
  286. Xint dflag=1;    /* ... sort hostnames within domains */
  287. Xint Dflag=0;    /* ... show users in a given domain */
  288. Xint hflag=0;    /* ... show users on a given host */
  289. Xint lflag=0;    /* ... show hosts with given user */
  290. Xint rflag=0;    /* ... retro -- imitiate rwho */
  291. Xint uflag=0;    /* ... show uptimes (like ruptime) */
  292. Xint wflag=0;    /* ... break lines before wraparound */
  293. Xint errflag=0;
  294. X
  295. Xint wlim=80;    /* default screen width */
  296. X
  297. Xextern char *rindex(), *malloc(), *getenv();
  298. X
  299. Xmain(argc, argv)
  300. Xint argc;
  301. Xchar *argv[];
  302. X{
  303. X    DIR *dirp;
  304. X    struct direct *dp;
  305. X    int rwfcmp(), rutcmp(), drwcmp();    /* qsort() routines */
  306. X    extern int optind;    /* see getopt(3C) */
  307. X    extern char *optarg;    /* see getopt(3C) */
  308. X
  309. X    program = argv[0];
  310. X    now = time(0);
  311. X    rutsize = sizeof(rut);
  312. X    hdrsize = sizeof(hdr);
  313. X
  314. X    while ((n = getopt(argc, argv, "acdhlmrsuwD:")) != EOF)
  315. X        switch(n) {
  316. X        case 'a': aflag=0; break;    /* same as rwho(1) */
  317. X        case 'c': cflag=1; break;    /* show login count */
  318. X        case 'd': dflag=0; break;    /* domain-wise sort */
  319. X        case 'm': mflag=0; break;    /* show multi-logins */
  320. X        case 'r': rflag++; break;    /* rwho-style output */
  321. X        case 's': sflag=0; break;    /* domain-only lists */
  322. X        case 'u': uflag++; break;    /* show uptimes */
  323. X        case 'w': wflag++; break;    /* break long lines */
  324. X        case 'D': Dflag++; domain = optarg; break;
  325. X        case 'h': hflag++; break;    /* host-list follows */
  326. X        case 'l': lflag++; break;    /* user-list follows */
  327. X        default: errflag++;
  328. X        }
  329. X
  330. X    /*
  331. X     * Note: -h and -l are mutually exclusive since both options
  332. X     * use the remaining arguments as a search list. Either option
  333. X     * should be followed by at least one name.  The getopt switch
  334. X     * could have been arranged to only use whichever flag (l or h)
  335. X     * was typed last but this way the user will know that there is
  336. X     * a potential problem.
  337. X     */
  338. X    if (errflag || (lflag && hflag)
  339. X        || (optind >= argc && (lflag || hflag))) {
  340. X        fprintf(stderr, "Usage: %s [-acdmrsuw] [-D domain] [-h host ... | -l user ... ]\n", program);
  341. X        exit(1);
  342. X    }
  343. X
  344. X    if (!dflag || lflag || rflag || uflag) sflag=0;
  345. X    if (!mflag) cflag=0;    /* not really needed (see burp()) */
  346. X
  347. X    if (chdir(RWHODIR) < 0) {    /* cd RWHODIR */
  348. X        perror(RWHODIR);
  349. X        exit(1);
  350. X    }
  351. X
  352. X    if (wflag) {    /* wrapping, eh? ok, get screen width */
  353. X        int n;
  354. X        char buf[1024];
  355. X
  356. X        if ((hp = getenv("TERM")) == NULL) {
  357. X            wflag = 0;
  358. X#ifdef SQUAWK
  359. X            fprintf(stderr, "%s: no TERM?\n", program);
  360. X#endif
  361. X        }
  362. X        if (wflag && tgetent(buf, hp) < 0) {
  363. X            wflag = 0;
  364. X#ifdef SQUAWK
  365. X            fprintf(stderr, "%s: no TERMCAP?\n", program);
  366. X#endif
  367. X        }
  368. X        if (wflag && (n = tgetnum("co")) > 0 && n > MRGN+MINSTR)
  369. X            wlim = n;
  370. X    }
  371. X
  372. X    if (hflag) {
  373. X        sflag=0;
  374. X        for ( ;optind < argc; optind++)
  375. X            dohost(argv[optind]);
  376. X        exit(0);
  377. X    }
  378. X
  379. X    /*
  380. X     * read "." directory (assuming chdir() worked), 
  381. X     * and get all files with the "whod." prefix.
  382. X     * if Dflag, only get files ending with "domain".
  383. X     */
  384. X    if ((dirp = opendir(".")) == NULL
  385. X        || stat(".", &st) < 0) { 
  386. X        perror(RWHODIR);
  387. X        exit(1);
  388. X    }
  389. X    dp = readdir(dirp);    /* get "." */
  390. X    n = (st.st_size/(DIRSIZ(dp)+8))*RWFSZ;
  391. X    hnbuf = malloc((unsigned)n);
  392. X    n = 0; ep = hnbuf;
  393. X    while (dp = readdir(dirp)) {
  394. X        strncpy(ep, dp->d_name, dp->d_namlen);
  395. X        *(ep+dp->d_namlen) = '\0';
  396. X        if (strncmp(ep, "whod.", 5) == 0 &&
  397. X           (!Dflag || strcmp(rindex(ep,'.')+1,domain) == 0)) {
  398. X            ep += RWFSZ;
  399. X            n++;
  400. X        }
  401. X    }
  402. X    /* ep should now point to the end of the host name buffer */
  403. X    closedir(dirp);
  404. X
  405. X    if (dflag)    /* sort host names within domains */
  406. X        qsort(hnbuf, n, RWFSZ, drwcmp);
  407. X    else        /* sort full host name */
  408. X        qsort(hnbuf, n, RWFSZ, rwfcmp);
  409. X
  410. X    if (sflag) {    /* process by domains only */
  411. X        dodomains();
  412. X        exit(0);
  413. X    }
  414. X
  415. X    /*
  416. X     * process each "whod." file in hnbuf list.
  417. X     * - get <filesize> bytes of mem
  418. X     * - gobble rutmp data from file
  419. X     * - sort names alphabetically
  420. X     * - print names (burp)
  421. X     * - free up mem
  422. X     */
  423. X    hp = hnbuf;
  424. X    while (hp < ep) {
  425. X        if ((fd = open(hp, O_RDONLY)) < 0
  426. X            || fstat(fd, &st) < 0) {
  427. X            perror(hp);
  428. X            exit(1);
  429. X        }
  430. X        if ((n = st.st_size-hdrsize) || uflag) {
  431. X            if ((rubuf = malloc((unsigned)n)) == 0) {
  432. X                perror(program);
  433. X                exit(1);
  434. X            }
  435. X            n = read(fd, (char *)&hdr, hdrsize);
  436. X            n = ldrut(fd,rubuf,st.st_size-hdrsize);
  437. X            if (uflag)
  438. X                slurp(&hdr, n/rutsize);
  439. X            else
  440. X#ifdef debug
  441. X            if (n > 0){
  442. X#else
  443. X            if (now-hdr.rcvd <= RWPERIOD && n > 0){
  444. X#endif
  445. X                qsort(rubuf, n/rutsize, rutsize, rutcmp);
  446. X                if (!lflag || chew(rubuf,n,argc,argv))
  447. X                    burp(hp, rubuf, n);
  448. X            }
  449. X        }
  450. X        free(rubuf);
  451. X        close(fd);
  452. X        hp += RWFSZ;
  453. X    }
  454. X}
  455. X
  456. X/*
  457. X * compare rwho spool-file names
  458. X */
  459. Xrwfcmp(p, q)
  460. Xregister char *p, *q;
  461. X{
  462. X    return(strncmp(p, q, RWFSZ));
  463. X}
  464. X
  465. X/*
  466. X * compare utmp name entries
  467. X */
  468. Xrutcmp(p, q)
  469. Xregister struct rw_utmp *p, *q;
  470. X{
  471. X    return(strncmp(p->name, q->name, MINSTR));
  472. X} 
  473. X
  474. X/*
  475. X * compare sub-domain names
  476. X */
  477. Xdrwcmp(p, q)
  478. Xregister char *p, *q;
  479. X{
  480. X    int x;
  481. X    char *s, *t;
  482. X
  483. X    s = rindex(p, '.');
  484. X    t = rindex(q, '.');
  485. X    if (s) s++; else s = p;
  486. X    if (t) t++; else t = q;
  487. X    if(x = strncmp(s, t, RWFSZ))
  488. X        return(x);
  489. X    return(strncmp(p, q, RWFSZ));
  490. X}
  491. X
  492. X/*
  493. X * print "host:       user1 user2 ... "
  494. X *    or whatever format the flags dictate.
  495. X * (blame creeping featurism for this mass of spaghetti)
  496. X */
  497. Xburp(s, r, n)
  498. Xregister char *s, *r;
  499. Xint n;
  500. X{    
  501. X    int wdent;
  502. X    register int l, wo, sl;
  503. X    register char *xp;
  504. X    char tbuf[RWFSZ+MINSTR+2];
  505. X
  506. X    if (!sflag) s += 5;        /* skip "whod." prefix */
  507. X
  508. X    if (rflag) {    /* rwho-like output */
  509. X        register struct rw_utmp *rp;
  510. X
  511. X        sprintf(tbuf, "%.*s:", HNSZ, s);
  512. X        sl = strlen(tbuf);
  513. X        for (xp = r; xp < (r+n); xp += rutsize) {
  514. X            rp = (struct rw_utmp *)xp;
  515. X            strncpy(tbuf + sl, rp->tty, MINSTR);
  516. X            printf("%-8.8s %-23s %.12s",
  517. X                 rp->name, tbuf, ctime(&rp->time) + 4);
  518. X            if (rp->idle < 60)
  519. X                printf("\n");
  520. X            else {
  521. X                l = rp->idle/HOUR;
  522. X                wo = (rp->idle % HOUR)/60;
  523. X                if (l > 99)
  524. X                    wo = 59, l = 99;
  525. X                printf((l) ? " %2d" : "   ", l);
  526. X                printf(":%02d\n", wo);
  527. X            }
  528. X        }
  529. X        return;
  530. X    }
  531. X
  532. X    /* print host- or domain-name */
  533. X    if (sflag && cflag)    /* include # of hosts in domain */
  534. X        sprintf(tbuf, "%.*s/%d:", MRGN, s, sflag);
  535. X    else
  536. X        sprintf(tbuf, "%.*s:", MRGN+((!sflag) * 4), s);
  537. X
  538. X    printf("%-*s", wo = wdent = MRGN+((!sflag) * 5), s = tbuf);
  539. X
  540. X    if (n && mflag) {    /* print "user1 user2 ..." */
  541. X        for(l=0, xp=s=r+MINSTR; s < (r+n); s += rutsize)
  542. X            if (strncmp(s, xp, MINSTR)) {
  543. X                sprintf(tbuf,
  544. X                    (l>1)?" %.*s/%d":" %.*s",
  545. X                    MINSTR, xp, l);
  546. X                if (wflag) {    /* wrap and indent */
  547. X                    if ((sl=strlen(tbuf)) > wlim-wo)
  548. X                        printf("\n%*s",
  549. X                            wo = wdent, "");
  550. X                    wo += sl;
  551. X                }
  552. X                fputs(tbuf, stdout);
  553. X                xp = s; l = cflag;
  554. X            }
  555. X            else
  556. X                l += cflag;
  557. X        /* still one name left to do */
  558. X        sprintf(tbuf,(l>1)?" %.*s/%d\n":" %.*s\n",MINSTR,xp,l);
  559. X        if (wflag && (strlen(tbuf)-1) > wlim - wo)
  560. X            printf("\n%*s", wo = wdent, "");
  561. X        fputs(tbuf, stdout);
  562. X        return;
  563. X    }
  564. X
  565. X    /* ... else don't ignore multi-logins */
  566. X    for (s = r+MINSTR; s < (r+n); s += rutsize) {
  567. X        if (wflag) {    /* wrap and indent */
  568. X            if ((sl = strlen(s)) > MINSTR)
  569. X                sl = MINSTR;
  570. X            if (++sl > wlim - wo)
  571. X                printf("\n%*s", wo = wdent, "");
  572. X            wo += sl;
  573. X        }
  574. X        printf(" %.*s", MINSTR, s);
  575. X    }
  576. X    printf("\n");
  577. X}
  578. X
  579. X/*
  580. X * print uptimes (like ruptime(1))
  581. X */
  582. Xslurp(h, n)
  583. Xstruct rw_hdr *h;
  584. Xint n;
  585. X{
  586. X    char tbuf[128];
  587. X    register char *p;
  588. X    register int tdif;
  589. X
  590. X    /* host name */
  591. X    p = tbuf;
  592. X    sprintf(p, "%-15.15s", h->host);
  593. X
  594. X    /* if rcvd-time is >1 hour old then assume host is down */
  595. X    tdif = now - h->rcvd; p += 15;
  596. X    if (tdif > HOUR) {
  597. X        if (tdif > (24 * HOUR)) 
  598. X            sprintf(p, "down %3d+%02d:%02d\n",
  599. X                (tdif / (24 * HOUR)),
  600. X                (tdif % (24 * HOUR)) / HOUR,
  601. X                (tdif % HOUR) / 60);
  602. X        else
  603. X            sprintf(p, "down %6d:%02d\n",
  604. X                tdif / HOUR, (tdif % HOUR) / 60);
  605. X        fputs(tbuf, stdout);
  606. X        return;
  607. X    }
  608. X
  609. X    /* print host's uptime but include a '*' if
  610. X     * rcvd-time is between 5 mins and 1 hour old */
  611. X    sprintf(p, "%c up ", (tdif > RWPERIOD) ? '*' : ' ');
  612. X    tdif = now - h->boot; p += 5;
  613. X    if (tdif < 1)    /* host's boottime > our current time */
  614. X        sprintf(p, "    ??:??");
  615. X    else if (tdif > (24 * HOUR)) 
  616. X        sprintf(p, "%3d+%02d:%02d",
  617. X            (tdif / (24 * HOUR)),
  618. X            (tdif % (24 * HOUR)) / HOUR,
  619. X            (tdif % HOUR) / 60);
  620. X    else
  621. X        sprintf(p, "%6d:%02d", tdif / HOUR, (tdif % HOUR) / 60);
  622. X
  623. X    /* print # of users and the 3 load numbers */
  624. X    p += 9;
  625. X    sprintf(p, ", %5d user%s load: %2d.%02d, %2d.%02d, %2d.%02d\n",
  626. X        n, (n == 1) ? ", " : "s,",
  627. X        h->loadav[0]/100, h->loadav[0]%100,
  628. X        h->loadav[1]/100, h->loadav[1]%100,
  629. X        h->loadav[2]/100, h->loadav[2]%100);
  630. X    fputs(tbuf, stdout);
  631. X}
  632. X
  633. X/*
  634. X * show users on a specific host
  635. X */
  636. Xdohost(host)
  637. Xchar *host;
  638. X{
  639. X    struct hostent *h, *gethostbyname();
  640. X
  641. X    /*
  642. X     * try to get host's proper name
  643. X     * and try to find the proper spool file
  644. X     */
  645. X    if((h = gethostbyname(host)) == NULL) {
  646. X        hp = malloc(strlen(host)+MINSTR);
  647. X        sprintf(hp, "whod.%s", host);
  648. X/*
  649. X        perror(host);
  650. X        return(1);
  651. X */
  652. X    }
  653. X    else {
  654. X        hp = malloc(strlen(h->h_name)+MINSTR);
  655. X        sprintf(hp, "whod.%s", h->h_name);
  656. X    }
  657. X    if ((fd = open(hp, O_RDONLY)) < 0 && h != NULL) {
  658. X        char **s;
  659. X        /*
  660. X         * can't find file related to h_name
  661. X         * try the aliases instead.
  662. X         */
  663. X        s = h->h_aliases;
  664. X        while(*s) {
  665. X            free(hp);
  666. X            hp = malloc(strlen(*s)+MINSTR);
  667. X            sprintf(hp, "whod.%s", *s);
  668. X            if ((fd = open(hp, O_RDONLY)) > 0)
  669. X                break;
  670. X            s++;
  671. X        }
  672. X        if (*s == NULL) {
  673. X            fprintf(stderr,  "%s: no data\n",  host);
  674. X            return(1);
  675. X        }
  676. X    }
  677. X    if ((fd > 0 && fstat(fd, &st) < 0) || stat(hp, &st) < 0) {
  678. X        if (fd < 0)
  679. X            fprintf(stderr, "%s: unknown host\n", host);
  680. X        else
  681. X            perror(hp);
  682. X        return(1);
  683. X    }
  684. X    n = st.st_size - hdrsize;
  685. X    if ((rubuf = malloc((unsigned)n)) == 0) {
  686. X        perror(program);
  687. X        exit(1);
  688. X    }
  689. X    n = read(fd, (char *)&hdr, hdrsize);
  690. X    n = ldrut(fd,rubuf,st.st_size-hdrsize);
  691. X    if (uflag)
  692. X        slurp(&hdr, n/rutsize);
  693. X    else {
  694. X        if (now-hdr.rcvd > RWPERIOD)
  695. X            strcat(hp, "*");
  696. X        qsort(rubuf, n/rutsize, rutsize, rutcmp);
  697. X        burp(hp, rubuf, n);
  698. X    }
  699. X}
  700. X
  701. X/*
  702. X * show users by domain
  703. X */
  704. Xdodomains()
  705. X{
  706. X    int z;
  707. X    register int i;
  708. X    char *p0, *p1, *fnp, *rbp;
  709. X
  710. X    fnp = hp = hnbuf;
  711. X
  712. X    if ((rubuf = malloc(n * MAXPORTS * rutsize)) == NULL) {
  713. X        perror(program);
  714. X        exit(1);
  715. X    }
  716. X
  717. X    p0 = rindex(fnp, '.') + 1;
  718. X    if ((int)p0 == 1) p0 = fnp;
  719. X
  720. X    while (fnp < ep) {
  721. X        rbp = rubuf;
  722. X        for (p1=p0, n=i=0; fnp < ep && !strcmp(p1, p0); i++) {
  723. X            if ((fd = open(fnp, O_RDONLY)) < 0
  724. X                || fstat(fd, &st) < 0) {
  725. X                perror(fnp);
  726. X                exit(1);
  727. X            }
  728. X            read(fd, (char *)&hdr, hdrsize);
  729. X            z = ldrut(fd,rbp,st.st_size-hdrsize);
  730. X#ifdef debug
  731. X            if (z > 0) {
  732. X#else
  733. X            if (now-hdr.rcvd <= RWPERIOD && z > 0) {
  734. X#endif
  735. X                n += z;
  736. X                rbp += z;
  737. X            }
  738. X            close(fd);
  739. X            fnp += RWFSZ;
  740. X            p1 = p0;
  741. X            p0 = rindex(fnp, '.') + 1;
  742. X            if ((int)p0 == 1) p0 = fnp;
  743. X        }
  744. X        if (!n) continue;
  745. X        *rbp = '\0';
  746. X        qsort(rubuf, n/rutsize, rutsize, rutcmp);
  747. X        sflag = i;
  748. X        burp(p1, rubuf, n);
  749. X    }
  750. X    free(rubuf);
  751. X}
  752. X
  753. X/*
  754. X * load rutmp data into buffer.
  755. X */
  756. Xldrut(fd, p, n)
  757. Xint fd, n;
  758. Xchar *p;
  759. X{
  760. X    register int m1, m2, nr;
  761. X    register char *s;
  762. X
  763. X    if (!aflag) return(read(fd, p, n));
  764. X
  765. X    s = p;
  766. X    m1 = m2 = 0;
  767. X
  768. X    while (m2 < n && (nr = read(fd, s, rutsize)) > 0) {
  769. X        m2 += nr;
  770. X        if (((struct rw_utmp *)s)->idle > HOUR)
  771. X            /* ignore entries with >1 hr idle time */
  772. X            continue;
  773. X        m1 += nr;
  774. X        s += nr;
  775. X    }
  776. X    return(m1);
  777. X}
  778. X
  779. X/*
  780. X * search a file's data for given users
  781. X */
  782. Xchew(r, n, ac, av)
  783. Xchar *r, *av[];
  784. Xint n, ac;
  785. X{
  786. X    register int i;
  787. X    register char *p;
  788. X    extern int optind;
  789. X
  790. X    /* grotty old standard linear search */
  791. X    for (p = r+MINSTR; p < (r+n); p += rutsize)
  792. X        for (i=optind; i<ac; i++)
  793. X            if (*p == av[i][0]
  794. X                && !strncmp(av[i], p, MINSTR))
  795. X                return (1);
  796. X    return(0);
  797. X}
  798. END_OF_ru.c
  799. if test 13584 -ne `wc -c <ru.c`; then
  800.     echo shar: \"ru.c\" unpacked with wrong size!
  801. fi
  802. # end of overwriting check
  803. fi
  804. echo shar: End of shell archive.
  805. exit 0
  806.  
  807.